﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tracy.BasicServices;
using Tracy.DataModel;
using Tracy.Handlers;
using Tracy.DataServices;
using Tracy.DataModel.UltraExplorer;
using SharedLib.DataAccess;
using SharedLib.XmlDataModel;
using Tracy.DataServices.UltraExplorer;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using SharedLib.CrossCuttingFramework;

namespace Tracy
{
    /// <summary>
    /// General Access to Tracy Services & Resources
    /// </summary>
    public class TracyFacade:IDisposable
    {
        #region Singleton
        /// <summary>
        /// Get the singleton instance
        /// </summary>
        public static TracyFacade Instance
        {
            get { return SingletonHelper._instance; }
        }

        /// <summary>
        /// Nested helper class
        /// </summary>
        private class SingletonHelper
        {
            static SingletonHelper() { }
            internal static readonly TracyFacade _instance = new TracyFacade();
        }
        private TracyFacade()
        {
            //Pre init codes come here
        }
        #endregion

        private IUnityContainer _diContainer;
        /// <summary>
        /// DI Container from Unity
        /// </summary>
        public IUnityContainer DIContainer
        {
            get { return _diContainer; }
        }

        private FilterManager _filterManager = new FilterManager();

        public FilterManager FilterManager
        {
            get { return _filterManager; }
        }

        private TracyMessageDispatcher _messageDispatcher = new TracyMessageDispatcher();

        public TracyMessageDispatcher MessageDispatcher
        {
            get { return _messageDispatcher; }
        }

        private TracyPluginManager _pluginManager = new TracyPluginManager();

        public TracyPluginManager PluginManager
        {
            get { return _pluginManager; }
        }

        public IDataProvider<T> GetDataProvider<T>() where T: XmlDataModelWithAttributesAndID, new()
        {
            if (typeof(T) == typeof(Entry))
                return (IDataProvider<T>)EntryProvider;
            else if (typeof(T) == typeof(Resource))
                return (IDataProvider<T>)ResourceProvider;
            else if (typeof(T) == typeof(MediaFile))
                return (IDataProvider<T>)MediaFileProvider;

            return null;
        }

        public IClassifierProvider<T> GetClassifierProvider<T>() where T : XmlDataModelWithAttributesAndID, new()
        {
            if (typeof(T) == typeof(Entry))
                return (IClassifierProvider<T>)EntryClassifierProvider;
            //else if (typeof(T) == typeof(MediaFile))
            //    return (IClassifierProvider<T>)FileClassifierProvider;

            return null;
        }

        private EntryProvider _entryProvider = new EntryProvider();

        public EntryProvider EntryProvider
        {
            get { return _entryProvider; }
        }

        

        private ResourceProvider _resourceProvider = new ResourceProvider();

        public ResourceProvider ResourceProvider
        {
            get { return _resourceProvider; }
        }

        private MediaFileProvider _mediaFileProvider = new MediaFileProvider();

        public MediaFileProvider MediaFileProvider
        {
            get { return _mediaFileProvider; }
        }

        private TaskScheduler _taskScheduler = new TaskScheduler();

        public TaskScheduler TaskScheduler
        {
            get { return _taskScheduler; }
        }

        private DownloadManager _downloadManager = new DownloadManager();

        public DownloadManager DownloadManager
        {
            get { return _downloadManager; }
        }

        SearchEngine _searchEngine = new SearchEngine();

        public SearchEngine SearchEngine
        {
            get { return _searchEngine; }
        }

        private TagManager _tagManager = new TagManager();
        public TagManager TagManager
        {
            get { return _tagManager; }
        }

        private UserPreferenceManager _userPreferenceManager = new UserPreferenceManager();
        public UserPreferenceManager UserPreferenceManager
        {
            get { return _userPreferenceManager; }
        }

        EntryClassifierProvider _entryClassifierProvider = new EntryClassifierProvider();

        public EntryClassifierProvider EntryClassifierProvider
        {
            get { return _entryClassifierProvider; }
        }

        public void Initialize()
        {
            //Init codes come here
            InitEnterpriseLibrary();

            InitMessageDispatcher();

            InitPlugins();

            TaskScheduler.LoadSettings(null);

            InitDataProviders();
        }

        private void InitEnterpriseLibrary()
        {
            _diContainer = new UnityContainer();

            //Load from custom file
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap { ExeConfigFilename = "Unity.config" };
            System.Configuration.Configuration configuration =
                ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            UnityConfigurationSection unitySection = (UnityConfigurationSection)configuration.GetSection("unity");

            _diContainer.LoadConfiguration(unitySection);

        }

        private void InitDataProviders()
        {
            EntryProvider.LoadItems();
            ResourceProvider.LoadItems();
            MediaFileProvider.LoadItems();
        }

        private void InitMessageDispatcher()
        {
            MessageDispatcher.SetHandlerCapacity(typeof(FeedScanHandler).Name, 1); //must process one by one
            MessageDispatcher.SetHandlerCapacity(typeof(FileMonitorHandler).Name, 1); //must process one by one
            MessageDispatcher.SetHandlerCapacity(typeof(CopyFileHandler).Name, 1);//must process one by one

            MessageDispatcher.SetHandlerCapacity("GetXmlFromURLHandler_KTXP", 5); //More threads for KTXP RSS reading
            MessageDispatcher.SetHandlerCapacity("GetDataFromURLHandler_VeryCD", 5); //More threads for VeryCD HTML reading
            MessageDispatcher.SetHandlerCapacity("GetXmlFromURLHandler_VeryCD", 10); //More threads for VeryCD RSS reading
        }

        private void InitPlugins()
        {
            PluginManager.LoadPlugins();

            //Load plugin classes to DI container
            foreach (Type interfaceType in PluginManager.RegisteredClasses.Keys)
            {
                IDictionary<string, Type> classDict = PluginManager.RegisteredClasses[interfaceType];
                foreach (string name in classDict.Keys)
                {
                    Type classType = classDict[name];
                    _diContainer.RegisterType(interfaceType, classType, name);
                }
            }
        }

        public void Dispose()
        {
            TaskScheduler.StopTimer();
            MessageDispatcher.Stop();
        }
    }
}
